﻿namespace Arms.Persistence
{
    using Arms.Domain;
    using Arms.Domain.Modules.Geography;
    using Arms.Framework;
    using Arms.Framework.Security;
    using Arms.Framework.Validators;
    using System;
    using System.Data.Entity;

    /// <summary>
    /// Arms unit of work.
    /// </summary>
    public class ArmsUnitOfWork : IUnitOfWork
    {
        private readonly IUser _user;
        private IDbContext _context;

        public ArmsUnitOfWork(IDbContext context, IUser user)
        {
            _context = Validation.Ensure(context);
            _user = Validation.Ensure(user);
        }

        /// <summary>
        /// User who is using this unit of work.
        /// </summary>
        public IUser User
        {
            get { return _user; }
        }
        /// <summary>
        /// Save changes.
        /// </summary>
        public void Commit()
        {
            _context.ChangeTracker.Entries().ForEach(entry =>
            {
                Entity entity = entry.Entity as Entity;
                entity.Updated = DateTime.UtcNow;
                entity.UpdatedUserID = _user.HasIdentity ? _user.UserID : 0;

                if (entry.State == EntityState.Added)
                {
                    entity.Created = DateTime.UtcNow;
                    entity.CreatedUserID = _user.HasIdentity ? _user.UserID : 0;
                }
            });
            _context.SaveChanges();
        }
        /// <summary>
        /// Repository.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IRepository<T> Repository<T>() where T : Entity
        {
            return new Repository<T>(_context);
        }
        #region IDisposable Members

        private bool _disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!_disposed)
                {
                    _context.Dispose();
                }
            }
            _disposed = true;
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
